package wsepForum.domain.handlers;

import java.text.SimpleDateFormat;
import java.util.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import wsepForum.common.elements.*;
import wsepForum.domain.exceptions.SystemFailureException;
import wsepForum.domain.exceptions.UnAuthorizedException;
import wsepForum.persistance.IPersistentHandler;
import wsepForum.persistance.exceptions.DataBaseIOException;
import wsepForum.persistance.exceptions.WrongUserNameException;

/**
 * The main interface between the GUI layer and the domain layer.
 * Provides the transportation of information between the GUI and the persistent.
 * Each further inheritance implements/overrides the services a certain user group
 * can receive from the system.
 *
 * This handler deals with a moderator user
 *
 * @author Amir Harel & Ariel Rozen & Oren Ben-Haim
 *
 */
public class ModeratorHandler extends MemberHandler {

	/*****************************
	 * CONSTRUCTOR               *
	 *****************************/
	/**
	 * @param user An object that holds information about the logged-in user
	 * @param persistent The interface supplied by the persistent layer.
	 */
	public ModeratorHandler(User user, IPersistentHandler persistent) {
		super(user, persistent);
	}

	/*****************************
	 * METHODS                   *
	 *****************************/

	/**
	 * A moderator can edit is own messages,
	 * and other messages belong the section he manages,
	 * but not messages of an admin.
	 *
	 * @param messageToEdit The message to edit
	 * @parem sectionID the section in which the message is in
	 * @return true, if allowed to edit the message
	 */
	@Override
	public boolean editMessageAuthentication(Message messageToEdit, int sectionID) throws SystemFailureException {
		try {
			if(messageToEdit.getUserName() != null) {
				User writer = this.getPersistent().getUser(messageToEdit.getUserName());
				return (super.editMessageAuthentication(messageToEdit, sectionID)
						|| ((writer.getUserType().compareTo(this.getUser().getUserType())<=0)
						&& this.getUser().hasSection(sectionID)));
			}
			else return this.getUser().hasSection(sectionID);
		} catch (WrongUserNameException e) {
			return (super.editMessageAuthentication(messageToEdit, sectionID)
					&& this.getUser().hasSection(sectionID));
		} catch (DataBaseIOException e) {
			throw new SystemFailureException(e);
		}

	}

	/**
	 * A moderator can delete it's own messages,
	 * and other messages belong the section he manages,
	 * but not messages of an admin.
	 *
	 * @param messageToDelete The message to delete
	 * @return true, if allowed to edit the message
	 */
	@Override
	public boolean deleteMessageAuthentication(Message messageToDelete, int sectionID) throws SystemFailureException {
		try {
			if(messageToDelete.getUserName() != null) {
				User writer = this.getPersistent().getUser(messageToDelete.getUserName());
				return (super.deleteMessageAuthentication(messageToDelete, sectionID)
						|| ((writer.getUserType().compareTo(this.getUser().getUserType())<=0)
						&& this.getUser().hasSection(sectionID)));
			}
			else return this.getUser().hasSection(sectionID);
		} catch (WrongUserNameException e) {
			return (super.deleteMessageAuthentication(messageToDelete, sectionID)
					&& this.getUser().hasSection(sectionID));
		} catch (DataBaseIOException e) {
			throw new SystemFailureException(e);
		}
	}

	
	
	@Override
	public BufferedImage makeMessageCountStatistics(Date date) throws UnAuthorizedException {
		double[] msgCount = this.getPersistent().getMessageCountStatistics(date);

		BufferedImage chartImg = null;
		if(msgCount.length == 24){
			double avg = 0;
			final XYSeries msgPerHour = new XYSeries("Message per hour");
			for (int i = 0; i < msgCount.length; i++) {
				msgPerHour.add(i,msgCount[i]);
				avg += msgCount[i];
			}
			
			avg = avg/24;
	        
	        XYSeriesCollection dataset = new XYSeriesCollection();
	        dataset.addSeries(msgPerHour);
	        
	        JFreeChart chart = ChartFactory.createXYLineChart("Message sent each hour on " + new SimpleDateFormat("dd-MM-yyyy").format(date),"Hour","Messaages Sent",
	        						dataset,PlotOrientation .VERTICAL,false,true,false);
	        
	        chartImg = this.setProperties(chart,700,500,avg, 23);
		}
		return chartImg;
	}

	@Override
	public BufferedImage makeUserCountStatistics(Date date) throws UnAuthorizedException {
		double[] usrCount = this.getPersistent().getUserCountStatistics(date);
		
        BufferedImage chartImg = null;
        
		if(usrCount.length == 24){
			double avg = 0;
			final XYSeries usrPerHour = new XYSeries("User per hour");
			for (int i = 0; i < usrCount.length; i++) {
				usrPerHour.add(i,usrCount[i]);
				avg += usrCount[i];
			}
			
			avg = avg/24;
	        
	        XYSeriesCollection dataset = new XYSeriesCollection();
	        dataset.addSeries(usrPerHour);
	        
	        JFreeChart chart = ChartFactory.createXYLineChart("User conected each hour on " + new SimpleDateFormat("dd-MM-yyyy").format(date),"Hour","User Connected",
	        						dataset,PlotOrientation .VERTICAL,false,true,false);
	        
	        chartImg = this.setProperties(chart,700,500,avg, 23);
		}
		return chartImg;
	}

	@Override
	public BufferedImage makeUserMessagePerDay(Date fromDate, String user) throws UnAuthorizedException {
		
		double[] usrMsg = this.getPersistent().getUserMessagePerDay(fromDate, user);
		BufferedImage chartImg = null;
		if(usrMsg.length == 31){
			double avg = 0;
			final XYSeries msgPerHour = new XYSeries("User message per day");
			for (int i = 0; i < usrMsg.length; i++) {
				msgPerHour.add(i,usrMsg[i]);
				avg += usrMsg[i];
			}
			
			avg = avg/31;
	        
	        XYSeriesCollection dataset = new XYSeriesCollection();
	        dataset.addSeries(msgPerHour);
	        
	        JFreeChart chart = ChartFactory.createXYLineChart("Message sent by " + user + " each day from " + new SimpleDateFormat("dd-MM-yyyy").format(fromDate),"Day","",
	        						dataset,PlotOrientation .VERTICAL,false,true,false);
	        
	        chartImg = this.setProperties(chart,700,500,avg, 31);
		}
        return chartImg;
	}
	
	private BufferedImage setProperties(JFreeChart chart, int width, int height, double avg, int quantum){
        chart.setBackgroundPaint(Color.white);
        XYPlot plot = chart.getXYPlot();
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        
        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
        renderer.setSeriesLinesVisible(0, true);
        renderer.setSeriesShapesVisible(0, true);
        renderer.setSeriesPaint(0, Color.blue);
        plot.setRenderer(renderer);

        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        
        NumberAxis domain = new NumberAxis("Day") ;
        domain.setAutoTickUnitSelection(false) ;
        domain.setRange(0, quantum) ;
        chart.getXYPlot().setDomainAxis(domain) ;
        
		BufferedImage chartImg = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); 
		Graphics2D grafics = chartImg.createGraphics();
		chart.draw(grafics, new Rectangle2D.Double(0, 0, width, height));
		grafics.setFont(new Font("Arial",Font.BOLD,18));
		grafics.setColor(Color.black);
        grafics.drawString("avarege = " + avg, width/2-50, height/5); 
		grafics.dispose();
		
		return chartImg;

	}


}
